package s.f.util;

import s.f.empresas.Empresas;
import s.f.empleados.CRUD_Empleados;
import s.f.empleados.Empleados;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

/**
 * Validacion para el registro de personas fisicas y morales.
 *
 * @author Froy
 */
public class Validacion {

    /**
     * Expresión Regular para CURP (Clave Única de Registro de Población).
     * <p>01-Primera letra del apellido paterno.</p> <p>02-Primera vocal del
     * mismo apellido paterno.</p> <p>03-Primera letra del apellido materno. De
     * no existir un apellido materno se utiliza (X).</p> <p>04-Primera letra
     * del primer nombre.</p> <p>05-Año de nacimiento 85</p> <p>06-Mes de
     * nacimiento 07</p> <p>07-Día de nacimiento 11</p> <p>08-H|M genero</p>
     * <p>09-2 elementos de entidad la entidad federativa <a
     * href="http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp">info</a></p>
     * <p>10-3 elementos primera constante de Ap.Paterno / Ap.Materno / Nombre
     * de Pila</p> <p>11-1 elemento Homoclave [A-Z0-9]</p> <p>12-1 elemento
     * Dígito verificador [0-9]</p>
     */
    public static final String REGEXPCURP = "^[A-Z&][AEIOUX][A-Z&]{2}[0-9]{2}[0-1][0-9][0-3][0-9][MH]([A][S]|[A][S]|[B][C]|[B][S]|[C][C]|[C][S]|[C][H]|[C][L]|[C][M]|[D][F]|[D][G]|[G][T]|[G][R]|[H][G]|[J][C]|[M][C]|[M][N]|[M][S]|[N][T]|[N][L]|[O][C]|[P][L]|[Q][T]|[Q][R]|[S][P]|[S][L]|[S][R]|[T][C]|[T][S]|[T][L]|[V][Z]|[Y][N]|[Z][S]|[N][E])[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]$";
    /**
     * Expresión Regular para RFC (Registro Federal de Contribuyentes).
     * <p>01-Primera letra del apellido paterno.</p> <p>02-Primera vocal del
     * mismo apellido paterno.</p> <p>03-Primera letra del apellido materno. De
     * no existir un apellido materno se utiliza (X).</p> <p>04-Primera letra
     * del primer nombre.</p> <p>05-Año de nacimiento 85</p> <p>06-Mes de
     * nacimiento 07</p> <p>07-Día de nacimiento 11</p> <p>08-3 Homoclave
     * designada por el SAT.</p> <p>Froylán Daniel Aguilar Flores -
     * AUFF8507114V0</p> <p>Nota: En un RFC no se permite la Ñ, se cambia por el
     * (ampersand) &</p>
     */
    public static final String REGEXPRFC = "^[A-Z&][A-Z&][A-Z&]{2}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]{3}$";
    public static final String REGEXPRFC2 = "^[A-Z&][AEIOUX][A-Z&]{2}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]{3}$";
    /**
     * Expresión Regular para el NSS (Número del Seguro Social) 11 dígitos
     * (pendiente).
     */
    public static final String REGEXPNSS = "[0-9]{11}";
    /**
     * Expresión Regular para el correo electrónico (Email).
     */
    public static final String REGEXPEMAIL = "^[a-z0-9]+(\\.[a-z0-9_-]+)*@[a-z0-9]+(\\.[a-z]+)*(\\.[a-z]{2,})$";
    /**
     * Expresión Regular para fecha.
     */
    public static final String REGEXPFECHA = "^((([0][1-9]|[12][0-9])|[3][01])[-]([0][13578]|[1][02])[-][1-9][0-9][0-9][0-9])|((([0][1-9]|[12][0-9])|[3][0])[-]([0][13456789]|[1][012])[-][1-9][0-9][0-9][0-9])|(([0][1-9]|[12][0-9])[-][0][2][-][1-9][0-9]([02468][048]|[13579][26]))|(([0][1-9]|[12][0-8])[-][0][2][-/][1-9][0-9][0-9][0-9])$";
    /**
     * Expresión Regular para fechas con formato: 02-02-2000 ó 02/02/2000.
     *
     * @deprecated Hasta el momento no esta siendo utilizada.
     */
    public static final String REGEXPFECHAS = "^((([0][1-9]|[12][0-9])|[3][01])[-/]([0][13578]|[1][02])[-/][1-9][0-9][0-9][0-9])|((([0][1-9]|[12][0-9])|[3][0])[-/]([0][13456789]|[1][012])[-/][1-9][0-9][0-9][0-9])|(([0][1-9]|[12][0-9])[-/][0][2][-/][1-9][0-9]([02468][048]|[13579][26]))|(([0][1-9]|[12][0-8])[-/][0][2][-/][1-9][0-9][0-9][0-9])$";
    public static final String URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
    public static final String EMAIL = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
    public static final String CADENA_NUMERICA_DE_SEIS = "\\d{6}";
    public static final String CONTRASENA_SEGURA = "(?=^.{8,}$)((?=.*\\d)|(?=.*\\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*";
    public static final String TARJETA_CREDITO = "^((67\\d{2})|(4\\d{3})|(5[1-5]\\d{2})|(6011))(-?\\s?\\d{4}){3}|(3[4,7])\\ d{2}-?\\s?\\d{6}-?\\s?\\d{5}$";
    public static final String DIRECION_IP4 = "^(1\\d{0,2}|2(?:[0-4]\\d{0,1}|[<wbr />6789]|5[0-5]?)?|[3-9]\\d?|0)\\.(<wbr />1\\d{0,2}|2(?:[0-4]\\d{0,1}|[<wbr />6789]|5[0-5]?)?|[3-9]\\d?|0)\\.(<wbr />1\\d{0,2}|2(?:[0-4]\\d{0,1}|[<wbr />6789]|5[0-5]?)?|[3-9]\\d?|0)\\.(<wbr />1\\d{0,2}|2(?:[0-4]\\d{0,1}|[<wbr />6789]|5[0-5]?)?|[3-9]\\d?|0)(\\/<wbr />(?:[012]\\d?|3[012]?)){0,1}$";
    public static final String DIRECCION_IP6 = "^[a-f0-9]{0,4}((\\:)?|(\\::)?)[<wbr />a-f0-9]{0,4}((\\:)?|(\\::)?)[a-<wbr />f0-9]{0,4}((\\:)?|(\\::)?)[a-f0-<wbr />9]{0,4}((\\:)?|(\\::)?)[a-f0-9]{<wbr />0,4}((\\:)?|(\\::)?)[a-f0-9]{0,<wbr />4}((\\:)?|(\\::)?)[a-f0-9]{0,4}(<wbr />(\\:)?|(\\::)?)[a-f0-9]{0,4}(\\/(<wbr />?:[01236]\\d?|1\\d[0-8]?)){0,1}$";
    public static final String YOUTUBE = "/http:\\/\\/(?:youtu\\.be\\/|(?:[a-z]{2,3}\\.)?youtube\\.com\\/watch(?:\\?|#\\!)v=)([\\w-]{11}).*/gi";
    
    //Atributos requeridos
    public String txtnombre = "";
    public String txtappaterno = "";
    public String txtfnacimiento = "";
    public String txtnss = "";
    public String txtrfc = "";
    public String txtcurp = "";
    public String txtemail = "";
    public String txtrazonsocial = "";
    public String txtfinscripcion;
    public String txtpais = "";
    public String txtestado = "";
    public String txtmunicipio = "";
    public String txtRFCrazonSocial = "";

    public String getTxtfinscripcion() {
        return txtfinscripcion;
    }

    public void setTxtfinscripcion(String txtfinscripcion) {
        this.txtfinscripcion = txtfinscripcion;
    }

    public String getTxtfnacimiento() {
        return txtfnacimiento;
    }

    public void setTxtfnacimiento(String txtfnacimiento) {
        this.txtfnacimiento = txtfnacimiento;
    }

    public String getTxtRFCrazonSocial() {
        return txtRFCrazonSocial;
    }

    public void setTxtRFCrazonSocial(String txtRFCrazonSocial) {
        this.txtRFCrazonSocial = txtRFCrazonSocial;
    }

    public String getTxtestado() {
        return txtestado;
    }

    public void setTxtestado(String txtestado) {
        this.txtestado = txtestado;
    }

    public String getTxtmunicipio() {
        return txtmunicipio;
    }

    public void setTxtmunicipio(String txtmunicipio) {
        this.txtmunicipio = txtmunicipio;
    }

    public String getTxtpais() {
        return txtpais;
    }

    public void setTxtpais(String txtpais) {
        this.txtpais = txtpais;
    }
    
    public String getTxtrazonsocial() {
        return txtrazonsocial;
    }

    public void setTxtrazonsocial(String txtrazonsocial) {
        this.txtrazonsocial = txtrazonsocial;
    }

    public String getTxtappaterno() {
        return txtappaterno;
    }

    public void setTxtappaterno(String txtappaterno) {
        this.txtappaterno = txtappaterno;
    }

    public String getTxtcurp() {
        return txtcurp;
    }

    public void setTxtcurp(String txtcurp) {
        this.txtcurp = txtcurp;
    }

    public String getTxtemail() {
        return txtemail;
    }

    public void setTxtemail(String txtemail) {
        this.txtemail = txtemail;
    }

    public String getTxtnombre() {
        return txtnombre;
    }

    public void setTxtnombre(String txtnombre) {
        this.txtnombre = txtnombre;
    }

    public String getTxtnss() {
        return txtnss;
    }

    public void setTxtnss(String txtnss) {
        this.txtnss = txtnss;
    }

    public String getTxtrfc() {
        return txtrfc;
    }

    public void setTxtrfc(String txtrfc) {
        this.txtrfc = txtrfc;
    }

    /**
     * Verificar si el portador de la fecha es mayor o menor de edad.
     *
     * @param fnacimiento
     * @return booleano
     */
    private static boolean isMayordeEdad(java.util.Date fnacimiento) {
        //dd-MM-yyyy
        Calendar calendario = Calendar.getInstance();
        boolean resultado = false;

        //Fecha Actual
        int anioActual = calendario.get(Calendar.YEAR);
        int mesActual = calendario.get(Calendar.MONTH) + 1;
        int diaActual = calendario.get(Calendar.DAY_OF_MONTH);

        calendario.setTime(fnacimiento);
        int anio = calendario.get(Calendar.YEAR);
        int mes = calendario.get(Calendar.MONTH) + 1;
        int dia = calendario.get(Calendar.DAY_OF_MONTH);
        
        if ((anioActual - anio) >= 18) {
            resultado = true;
        }

        return resultado;
    }

    /**
     * Verificar si el portador de la fecha es jubilado o no.
     *
     * @param fnacimiento
     * @return booleano
     */
    private static boolean isJubilado(java.util.Date fnacimiento) {
        //dd-MM-yyyy
        Calendar calendario = Calendar.getInstance();
        boolean resultado = false;

        //Fecha Actual
        int anioActual = calendario.get(Calendar.YEAR);
        int mesActual = calendario.get(Calendar.MONTH) + 1;
        int diaActual = calendario.get(Calendar.DAY_OF_MONTH);

        calendario.setTime(fnacimiento);
        int anio = calendario.get(Calendar.YEAR);
        int mes = calendario.get(Calendar.MONTH) + 1;
        int dia = calendario.get(Calendar.DAY_OF_MONTH);

        if ((anioActual - anio) >= 70) {
            resultado = true;
        }

        return resultado;
    }

    /**
     * Verfica y asigna si el elemento es requerido.
     *
     * @param elemento Solicita una cadena de texto el cual, será validado si
     * esta null o vacio.
     * @return Regresa una cadena de texto si el elemento requerido es null o
     * vacio.
     */
    public static String isRequerido(String elemento) {
        return (elemento == null || elemento.isEmpty()) ? "Este campo es requerido." : "";
    }
    
    /**
     * Verfica y asigna si el elemento es requerido.
     *
     * @param elemento Solicita una cadena de texto el cual, será validado si
     * esta null o vacio.
     * @return Regresa una cadena de texto si el elemento requerido es null o
     * vacio.
     */
    public static String isRequerido(int elemento) {
        return (elemento == -1) ? "Este campo es requerido." : "";
    }
    
    /**
     * Verfica y asigna si el elemento es requerido.
     *
     * @param elemento Solicita una cadena de texto el cual, será validado si
     * esta null o vacio.
     * @return Regresa una cadena de texto si el elemento requerido es null o
     * vacio.
     */
    public static String isRequerido(java.util.Date elemento) {
        return (elemento == null) ? "Este campo es requerido." : "";
    }
    
    /**
     * Válida si el elemento es null o vacio.
     *
     * @param elemento Solicita una cadena de texto para validar si viene null o
     * vacio.
     * @return Regresa el elemento con formato String si este es null o vacio.
     */
    public static String isNullorEmpty(String elemento) {
        return (elemento != null || !elemento.isEmpty()) ? elemento : "";
    }

    /**
     * Válida la curp con expresión regular.
     *
     * @param curp Solicita curp (Clave Única de Registro de Población)
     * @return Regresa true si de acuerdo a la expresión regular es válida en
     * otro caso regresa false.
     * @see #REGEXPCURP
     */
    public boolean valCurp(String curp) {
        return (curp.length() == 18) ? curp.matches(REGEXPCURP) : false;
    }

    /**
     * Válida el rfc con expresión regular.
     *
     * @param rfc Solicita rfc (Registro Federal de Contribuyentes) de una
     * persona física.
     * @return Regresa true si de acuerdo a la expresión regular es válida en
     * otro caso regresa false.
     * @see #REGEXPRFC
     */
    public boolean valRFC(String rfc) {
        return (rfc.length() == 13) ? rfc.matches(REGEXPRFC) : false;
    }

    /**
     * Válida el nss con expresión regular.
     *
     * @param nss Solicita nss (Número del Seguro Social)
     * @return Regresa true si de acuerdo a la expresión regular es válida en
     * otro caso regresa false.
     * @see #REGEXPNSS
     */
    public boolean valNSS(String nss) {
        return (nss.length() == 11) ? nss.matches(REGEXPNSS) : false;
    }

    /**
     * Válida el email con expresión regular.
     *
     * @param email Solicita Correo electrónico Email
     * @return Regresa true si de acuerdo a la expresión regular es válida en
     * otro caso regresa false.
     * @see #REGEXPEMAIL
     */
    public static boolean valEmail(String email) {
        return (email.matches(REGEXPEMAIL)) ? true : false;
    }

    /**
     * Válida la fecha con expresión regular.
     *
     * @param fecha Solicita fecha
     * @return Regresa true si de acuerdo a la expresión regular es válida en
     * otro caso regresa false.
     * @see #REGEXPFECHA
     */
    public boolean valFecha(java.util.Date fecha) {
        //Cambiar a String para compararla con la expresión regular.
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy", new Locale("es", "MX"));
        return sdf.format(fecha.getTime()).matches(REGEXPFECHA) ? true : false;
    }

    /**
     * Válida si es año bisiesto.
     *
     * @param anio Solicita año
     * @return Regresa true si es año bisiesto caso regresa false.
     * @deprecated Actualmente no se esta utilizando, se iba a utilizar para
     * validar la fecha.
     */
    public boolean valAnioBisiesto(int anio) {
        return (((anio % 4 == 0) && (anio % 100 != 0)) || (anio % 400 == 0)) ? true : false;
    }

    /**
     * Une el Nombre + Apellido Paterno + Apellido Materno.
     *
     * @param nombre Nombre
     * @param appaterno Apellido Paterno
     * @param apmaterno Apellido Materno
     * @return Regresa una cadena de texto en donde unifica el Nombre Apellido
     * Paterno y Apellido Materno.
     */
    public static String unirNombre(String nombre, String appaterno, String apmaterno) {
        return nombre + " " + appaterno + " " + apmaterno;
    }

    /**
     * Realiza un formato de fecha de la siguiente forma: dd de NombredelMes de
     * yyyy.
     *
     * @param fecha Solicita una fecha en el siguiente formato yyyy-MM-dd
     * @return Regresa una cadena de texto con el siguiente formato dd de
     * NombredelMes de yyyy.
     * @see #invertirFecha(java.lang.String)
     */
    public static String formatoFecha(String fecha) {
        String[] f = invertirFecha(fecha).split("-");
        String[] meses = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"};
        int mes = Integer.parseInt(f[1]) - 1;
        String dedel = (Integer.parseInt(f[2]) >= 2000) ? " del " : " de ";
        return f[0] + " de " + meses[mes] + dedel + f[2];
    }

    /**
     * Método para invertir una fecha ejem: 2009-12-23 a 23-12-2009.
     *
     * @param fecha Solicita una fecha
     * @return Regresa una fecha invertida. ejemplo: 2009-12-23 a 23-12-2009
     */
    public static String invertirFecha(String fecha) {
        String[] arrfecha = fecha.split("-");
        return arrfecha[2] + "-" + arrfecha[1] + "-" + arrfecha[0];
    }

    /**
     * Este método valida una forma de añadir y editar empleados.
     *
     * @param empleados Solicita objeto Empleado.
     * @param pagina Página a validar ejem. "Editar"
     * @return Devuelve el objeto Empleado.
     * @throws AppException
     * @see #isRequerido(java.lang.String)
     * @see #valFecha(java.lang.String)
     * @see #valEmail(java.lang.String)
     * @see #valNSS(java.lang.String)
     * @see CRUD_Empleados#getDuplicadoNSSbyCURP(java.lang.String,
     * java.lang.String)
     * @see #valRFC(java.lang.String)
     * @see CRUD_Empleados#getDuplicadoRFCbyCURP(java.lang.String,
     * java.lang.String)
     * @see #valCurp(java.lang.String)
     * @see CRUD_Empleados#getDuplicados(java.lang.String, java.lang.String)
     */
    public void validacionForma(Empleados empleados, String pagina) throws AppException {

        this.setTxtpais(Validacion.isRequerido(empleados.getPais()));
        this.setTxtestado(Validacion.isRequerido(empleados.getEstado()));
        this.setTxtmunicipio(Validacion.isRequerido(empleados.getMunicipio()));

        this.setTxtnombre(Validacion.isRequerido(empleados.getNombre()));
        this.setTxtappaterno(Validacion.isRequerido(empleados.getAppaterno()));

        this.setTxtfnacimiento(Validacion.isRequerido(empleados.getFnacimiento()));

        if (empleados.getFnacimiento() != null) {
            if (!this.valFecha(empleados.getFnacimiento())) {
                this.setTxtfnacimiento("Fecha no válida (dd-MM-yyyy) ejem. 29-02-2012");
            }
        }

        //Después de que la fecha es válida.
        if (empleados.getFnacimiento() != null && this.getTxtfnacimiento().isEmpty()) {

            String mayor = (Validacion.isMayordeEdad(empleados.getFnacimiento())) ? "" : "Es menor de edad";
            String jubilado = (Validacion.isJubilado(empleados.getFnacimiento())) ? "Es adulto jubilado" : mayor;

            this.setTxtfnacimiento(mayor);
            this.setTxtfnacimiento(jubilado);
        }

        if (!empleados.getEmail().isEmpty()) {
            if (!Validacion.valEmail(empleados.getEmail())) {
                this.setTxtemail("Email no válido");
            }
        }

        this.setTxtnss(Validacion.isRequerido(empleados.getNss()));
        if (!empleados.getNss().isEmpty()) {
            if (!this.valNSS(empleados.getNss())) {
                this.setTxtnss("NSS no válido ejem. 44444444444");
            } else {
                this.setTxtnss((CRUD_Empleados.getDuplicados("nss", empleados.getNss()) ? "NSS duplicada" : ""));
                if (pagina.equals("Editar")) {
                    this.setTxtnss((CRUD_Empleados.getDuplicadoNSSbyCURP(empleados.getNss(), empleados.getCurp()) ? "NSS duplicada en otra curp" : ""));
                }
            }
        }

        this.setTxtrfc(Validacion.isRequerido(empleados.getRfc()));
        if (!empleados.getRfc().isEmpty()) {
            if (!this.valRFC(empleados.getRfc())) {
                this.setTxtrfc("RFC no válido");
            } else {
                this.setTxtrfc((CRUD_Empleados.getDuplicados("rfc", empleados.getRfc()) ? "RFC duplicada" : ""));
                if (pagina.equals("Editar")) {
                    this.setTxtrfc((CRUD_Empleados.getDuplicadoRFCbyCURP(empleados.getRfc(), empleados.getCurp()) ? "RFC duplicada en otra curp" : ""));
                }
            }
        }

        this.setTxtcurp(Validacion.isRequerido(empleados.getCurp()));
        if (!empleados.getCurp().isEmpty()) {
            if (!this.valCurp(empleados.getCurp())) {
                this.setTxtcurp("CURP no válido");
            } else {
                if (!pagina.equals("Editar")) {
                    this.setTxtcurp((CRUD_Empleados.getDuplicados("curp", empleados.getCurp()) ? "CURP duplicada" : ""));
                }
            }
        }
    }

    /**
     * Utilizada para generar un password por default.
     *
     * @param passwordStd
     * @return
     * @deprecated
     */
    public String setGeneratePasswordDefault(String passwordStd) {
        String pass = "";

        return pass;
    }

    /**
     * Compara si dos palabras son iguales.
     *
     * @param palabra1
     * @param palabra2
     * @return
     */
    public static boolean comparar2Palabras(String palabra1, String palabra2) {
        return (palabra1.equals(palabra2)) ? true : false;
    }

    /**
     * Valida la forma para el registro de una persona moral.
     *
     * @param empresas
     * @param pagina
     * @return
     * @throws AppException
     */
    public Empresas validacionForma(Empresas empresas, String pagina) throws AppException {

        this.setTxtrazonsocial(Validacion.isRequerido(empresas.getRazonSocial()));

        this.setTxtfinscripcion(Validacion.isRequerido(empresas.getFinscripcion()));
        if (empresas.getFinscripcion() != null) {
            if (!this.valFecha(empresas.getFinscripcion())) {
                this.setTxtfinscripcion("Fecha no válida (dd-MM-yyyy) ejem. 29-02-2012");
            }
        }

        this.setTxtrfc(Validacion.isRequerido(empresas.getRfc()));

        return empresas;
    }
}